package com.farm.kaiping.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.farm.common.constant.CommonConstants;
import com.farm.common.security.SecurityUtils;
import com.farm.kaiping.entity.SysDict;
import com.farm.kaiping.entity.SysDictItem;
import com.farm.kaiping.mapper.SysDictItemMapper;
import com.farm.kaiping.po.SysDictPO;
import com.farm.kaiping.mapper.SysDictMapper;
import com.farm.kaiping.service.SysDictItemService;
import com.farm.kaiping.service.SysDictService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.farm.common.util.StringRange;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 字典表(SysDict)表服务实现类
 *
 * @author zhuhui
 * @since 2024-11-26 22:58:45
 */
@Service
@Slf4j
@AllArgsConstructor
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {

	private final SysDictItemMapper sysDictItemMapper;
	private final RedisTemplate redisTemplate;

	private LambdaQueryWrapper<SysDict> generateQueryWrapper(SysDictPO sysDictPO){
		LambdaQueryWrapper<SysDict> queryWrapper = new LambdaQueryWrapper<>();
		// 编号ID
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysDictPO.getId()), SysDict::getId, sysDictPO.getId());
		queryWrapper.in(ObjectUtil.isNotEmpty(sysDictPO.getIdList()), SysDict::getId, sysDictPO.getIdList());
		// 字典标识
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysDictPO.getIdentify()), SysDict::getIdentify, sysDictPO.getIdentify());
		// 字典名称
		queryWrapper.like(ObjectUtil.isNotEmpty(sysDictPO.getDictName()), SysDict::getDictName, sysDictPO.getDictName());
		// 类型
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysDictPO.getType()), SysDict::getType, sysDictPO.getType());
		// 描述
		queryWrapper.like(ObjectUtil.isNotEmpty(sysDictPO.getDescription()), SysDict::getDescription, sysDictPO.getDescription());
		// 备注
		queryWrapper.like(ObjectUtil.isNotEmpty(sysDictPO.getRemarks()), SysDict::getRemarks, sysDictPO.getRemarks());
		// 字典项数量
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysDictPO.getItemNum()), SysDict::getItemNum, sysDictPO.getItemNum());
		// 是否删除(0否1是)
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysDictPO.getDelFlag()), SysDict::getDelFlag, sysDictPO.getDelFlag());
        queryWrapper.eq(ObjectUtil.isEmpty(sysDictPO.getDelFlag()), SysDict::getDelFlag, 0);
		// 新增时间
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysDictPO.getCreateTime()), SysDict::getCreateTime, sysDictPO.getCreateTime());
		// 更新时间
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysDictPO.getUpdateTime()), SysDict::getUpdateTime, sysDictPO.getUpdateTime());
		// 租户ID
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysDictPO.getTenantId()), SysDict::getTenantId, sysDictPO.getTenantId());
		// 创建时间时间区间查询
		queryWrapper.ge(ObjectUtil.isNotEmpty(StringRange.getOne(sysDictPO.getCreateTimeBetween(),0)), SysDict::getCreateTime,StringRange.getOne(sysDictPO.getCreateTimeBetween(),0));
		queryWrapper.le(ObjectUtil.isNotEmpty(StringRange.getOne(sysDictPO.getCreateTimeBetween(),1)), SysDict::getCreateTime,StringRange.getOne(sysDictPO.getCreateTimeBetween(),1));
		// 更新时间时间区间查询
		queryWrapper.ge(ObjectUtil.isNotEmpty(StringRange.getOne(sysDictPO.getUpdateTimeBetween(),0)), SysDict::getUpdateTime,StringRange.getOne(sysDictPO.getUpdateTimeBetween(),0));
		queryWrapper.le(ObjectUtil.isNotEmpty(StringRange.getOne(sysDictPO.getUpdateTimeBetween(),1)), SysDict::getUpdateTime,StringRange.getOne(sysDictPO.getUpdateTimeBetween(),1));

		queryWrapper.orderByDesc(SysDict::getCreateTime,SysDict::getId);
		return queryWrapper;
	}

	 /**
	  * @describe 分页查询字典表
	  * @author zhuhui
	  * @date 2024-11-26 22:58:45
	  */
	@Override
	public Page<SysDict> getSysDictPage(Page page, SysDictPO sysDictPO){
		LambdaQueryWrapper<SysDict> queryWrapper = this.generateQueryWrapper(sysDictPO);
        return this.baseMapper.selectPage(page, queryWrapper);
	}
	
	/**
     * @describe 查询字典表list
     * @author  zhuhui
     * @date  2024-11-26 22:58:45
     */
	@Override
	public List<SysDict> getSysDictList(SysDictPO sysDictPO){
		LambdaQueryWrapper<SysDict> queryWrapper = this.generateQueryWrapper(sysDictPO);
        return this.baseMapper.selectList(queryWrapper);
	}
	
	/**
     * @describe 获取一条数据 字典表
     * @author  zhuhui
     * @date  2024-11-26 22:58:45
     */
	@Override
	public SysDict getSysDict(SysDictPO sysDictPO){
		LambdaQueryWrapper<SysDict> queryWrapper = this.generateQueryWrapper(sysDictPO);
        queryWrapper.last("LIMIT 1");
        return this.baseMapper.selectOne(queryWrapper);
	}

    /**
     * @describe 新增字典表
     * @author  zhuhui
     * @date  2024-11-26 22:58:45
     */
	@Override
	public Integer saveSysDict(SysDictPO sysDictPO) {
		if (ObjectUtil.isEmpty(sysDictPO.getIdentify())){
			throw new RuntimeException("字典标识为空");
		}
		if (ObjectUtil.isEmpty(sysDictPO.getDictName())){
			throw new RuntimeException("字典名称为空");
		}

		LambdaQueryWrapper<SysDict> existQueryWrapper = new LambdaQueryWrapper<>();
		existQueryWrapper.eq(SysDict::getIdentify, sysDictPO.getIdentify());
		existQueryWrapper.eq(SysDict::getDelFlag, 0);
		if (this.count(existQueryWrapper) > 0){
			throw new RuntimeException("字典标识重复");
		}

		sysDictPO.setDelFlag(0);
		sysDictPO.setTenantId(SecurityUtils.getUser().getTenantId());// 租户ID
		sysDictPO.setCreateTime(LocalDateTime.now());
		sysDictPO.setUpdateTime(LocalDateTime.now());
		SysDict sysDict = BeanUtil.copyProperties(sysDictPO, SysDict.class);
		this.save(sysDict);
		return sysDict.getId();
	}

	/**
     * @describe 修改字典表
     * @author  zhuhui
     * @date  2024-11-26 22:58:45
     */
	@Override
	public String updateSysDict(SysDictPO sysDictPO) {
		if (ObjectUtil.isEmpty(sysDictPO.getId())) {
			throw new RuntimeException("id为空");
		}

		SysDict sysDict1 = this.baseMapper.selectById(sysDictPO.getId());
		if (ObjectUtil.isEmpty(sysDict1)){
			throw new RuntimeException("数据不存在");
		}

		LambdaQueryWrapper<SysDict> existQueryWrapper = new LambdaQueryWrapper<>();
		existQueryWrapper.ne(SysDict::getId, sysDictPO.getId());
		existQueryWrapper.eq(SysDict::getIdentify, ObjectUtil.isEmpty(sysDictPO.getIdentify())?sysDict1.getIdentify():sysDictPO.getIdentify());
		existQueryWrapper.eq(SysDict::getDelFlag, 0);
		if (this.count(existQueryWrapper) > 0){
			throw new RuntimeException("字典标识重复");
		}

		sysDictPO.setUpdateTime(LocalDateTime.now());
		SysDict sysDict = BeanUtil.copyProperties(sysDictPO, SysDict.class);
		this.updateById(sysDict);
		return "修改成功";
	}

	/**
     * @describe 通过id删除字典表
     * @author  zhuhui
     * @date  2024-11-26 22:58:45
     */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String removeSysDict(SysDictPO sysDictPO) {
		if (ObjectUtil.isEmpty(sysDictPO.getBatchDel())) {
			throw new RuntimeException("删除数据未选择");
		}
		LambdaUpdateWrapper<SysDict> removeWrapper = new LambdaUpdateWrapper<>();
		removeWrapper.in(SysDict::getId, sysDictPO.getBatchDel());
		removeWrapper.set(SysDict::getDelFlag,1);
		removeWrapper.set(SysDict::getUpdateTime,LocalDateTime.now());
		this.update(removeWrapper);

		LambdaUpdateWrapper<SysDictItem> removeItemWrapper = new LambdaUpdateWrapper<>();
		removeItemWrapper.in(SysDictItem::getDictId, sysDictPO.getBatchDel());
		removeItemWrapper.set(SysDictItem::getDelFlag,1);
		removeItemWrapper.set(SysDictItem::getUpdateTime,LocalDateTime.now());
		sysDictItemMapper.update(null,removeItemWrapper);
		return "删除成功";
	}

	@Override
	public String refreshDictCache() {
		SysDictPO sysDictPO = new SysDictPO();
		List<SysDict> sysDictList = this.getSysDictList(sysDictPO);
		if (ObjectUtil.isNotEmpty(sysDictList)){
			List<Integer> dictIds = sysDictList.stream().map(SysDict::getId).collect(Collectors.toList());
			List<SysDictItem> sysDictItemList = sysDictItemMapper.selectList(Wrappers.<SysDictItem>query().lambda().in(SysDictItem::getDictId, dictIds).eq(SysDictItem::getDelFlag, 0));
			Map<Integer, List<SysDictItem>> sysDictItemMap = sysDictItemList.stream().collect(Collectors.groupingBy(SysDictItem::getDictId));

			sysDictList.forEach(sysDict -> {
				if (ObjectUtil.isNotEmpty(sysDictItemMap.get(sysDict.getId()))){
					sysDict.setItemList(sysDictItemMap.get(sysDict.getId()));
					sysDict.setItemNum(sysDictItemMap.get(sysDict.getId()).size());
				}
				String jsonStr = JSON.toJSONStringWithDateFormat(sysDict, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat);
				redisTemplate.opsForValue().set(CommonConstants.DICT_CACHE+sysDict.getIdentify(), jsonStr);
			});
		}
		return "刷新成功";
	}

	@Override
	public Map<String, List<SysDictItem>> getDictItemList(List<String> identifyList) {
		if (ObjectUtil.isEmpty(identifyList)){
			throw new RuntimeException("参数不存在");
		}

		Map<String, List<SysDictItem>> map = new HashMap<>();
		for (String s : identifyList) {
			Object o = redisTemplate.opsForValue().get(CommonConstants.DICT_CACHE + s);
            SysDict sysDict;
            if (o != null) {
                sysDict = JSONUtil.toBean(o.toString(), SysDict.class);
				map.put(s,sysDict.getItemList());
            }else {
				map.put(s,new ArrayList<>());
			}
		}
		return map;
	}

	@Override
	public Map<String, List<SysDictItem>> getDictItemGroupList(List<String> identifyList) {
		if (ObjectUtil.isEmpty(identifyList)){
			throw new RuntimeException("参数不存在");
		}

		Map<String, List<SysDictItem>> map = new HashMap<>();
		for (String s : identifyList) {
			Object o = redisTemplate.opsForValue().get(CommonConstants.DICT_CACHE + s);
			SysDict sysDict;
			if (o != null) {
				sysDict = JSONUtil.toBean(o.toString(), SysDict.class);
				List<SysDictItem> sysDictItemList = sysDict.getItemList();
				Map<String, SysDictItem> childdrenMap = new HashMap<>();
				for (SysDictItem sysDictItem : sysDictItemList) {
					SysDictItem sysDictItem1;
					if (ObjectUtil.isAllNotEmpty(sysDictItem.getType(),sysDictItem.getDescription())){
						if (ObjectUtil.isEmpty(childdrenMap.get(sysDictItem.getType()))){
							sysDictItem1 = new SysDictItem();
							sysDictItem1.setDictName(sysDictItem.getDescription());
							sysDictItem1.setLabel(sysDictItem.getDescription());
							sysDictItem1.setValue(sysDictItem.getType());
							sysDictItem1.setSort(sysDictItem.getSort());
							sysDictItem1.setDictId(sysDictItem.getDictId());
						}else{
							sysDictItem1 = childdrenMap.get(sysDictItem.getType());
						}
						if (ObjectUtil.isEmpty(sysDictItem1.getChildren())){
							sysDictItem1.setChildren(new ArrayList<>());
						}
						sysDictItem1.getChildren().add(sysDictItem);
						childdrenMap.put(sysDictItem.getType(),sysDictItem1);
					}
				}

				List<SysDictItem> listResult = new ArrayList<>(childdrenMap.values());
				map.put(s,listResult);
			}else {
				map.put(s,new ArrayList<>());
			}
		}

		return map;
	}
	
}

